package com.cooper.common.shiro.realm;

import com.cooper.base.model.SysUser;
import com.cooper.base.service.SysRoleMenuService;
import com.cooper.base.service.SysUserRoleService;
import com.cooper.base.service.SysUserService;
import com.cooper.common.util.PasswordUtil;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.util.Arrays;

/**
 * Copyright © 2017 com. All rights reserved.
 *
 * @Title: UserRealm.java
 * @Prject: springmvc-mybatis-shiro
 * @Package: com.cooper.common.shiro
 * @Description: Shiro用户鉴权和授权登录绑定
 * @author: JackCooperZ
 * @date: 2017年1月17日 下午5:37:10
 * @version: V1.0
 */
public class UserRealm extends AuthorizingRealm {

    @Resource
    private SysUserService sysUserService;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private SysRoleMenuService sysRoleMenuService;

    /**
     * 认证(登录时调用)
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //1.获取用户提交信息【用户名，密码】
        String username = (String) token.getPrincipal();
        String password = new String((char[]) token.getCredentials());
        SysUser record = new SysUser(username);
        //2.根据提交的用户名，从数据库中查询用户信息
        SysUser user = sysUserService.selectOne(record);
        //3.验证用户有效性
        if (user == null) {//用户不存在
            throw new UnknownAccountException("账号或密码不正确");
        }
        //4.验证密码
        String credential = PasswordUtil.encryptBySalt(password, user.getSalt());
        if (!credential.equals(user.getPassword())) {
            throw new IncorrectCredentialsException("账号或密码不正确");
        }
        //5.验证账号状态，是否锁定，0：锁定，1：启用
        if (user.getStatus() == 0) {
            throw new LockedAccountException("账号已被锁定,请联系管理员");
        }
        //6.返回验证信息
        return new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes(user.getSalt()), getName());
    }

    /**
     * 授权(验证权限时调用)
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        Object principal = principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        if (principal instanceof SysUser) {
            SysUser sysUser = (SysUser) principal;
            if ("admin".equals(sysUser.getUserName())) {
                authorizationInfo.addRole("admin");
            }
            //根据用户ID获取用户角色
            sysUserRoleService.listByUser(sysUser.getUserId()).forEach(sysRole -> {
                //遍历用户角色获取角色下菜单，将角色码绑定到用户
                authorizationInfo.addRole(sysRole.getRoleCode());
                sysRoleMenuService.listByRole(sysRole.getRoleId()).forEach(sysMenu -> {
                    //遍历角色下菜单，获取菜单对应的权限码
                    Arrays.asList(sysMenu.getPerms().split(",")).stream().forEach(perm -> {
                        //遍历角色下菜单中的权限码，将权限码绑定到用户
                        authorizationInfo.addStringPermission(perm);
                    });
                });
            });
        }
        return authorizationInfo;
    }


}
